"""
2048    核心算法
"""
map = [
    [4,0,2,0],
    [4,0,2,0],
    [2,0,0,2],
    [2,0,2,2]
]

#%% 1. 零元素移至末尾
#     [2,0,2,0] --> [2,2,0,0]
#     [2,0,0,2] --> [2,2,0,0]
#     [2,4,0,2] --> [2,4,2,0]
def zero_to_end(lie):
    """移动到末尾
    : 从后往前遍历，如果发现0元素则删除并在末尾追加0.
    """
    # -1 -2 -3 -4 -5 从最后一个到第一个
    for i in range(-1, -len(lie)-1, -1):
        if lie[i] == 0:
            lie.pop(i) # remove指定位置的0元素
            lie.append(0) # 在末尾追加0       
# zero_to_end(lie)
# print(lie)


#%% 2. 相同数值进行合并，忽视0并移至末尾
#     [2,2,0,0] --> [4,0,0,0]
#     [2,0,0,2] --> [4,0,0,0]
#     [2,0,4,0] --> [2,4,0,0]
def merge(lie):
    """
    先将中间的0元素移至末尾，在合并相邻相同元素
    """
    # 0移至末尾
    zero_to_end(lie)
    
    # 列表中前三个元素跟后面一位相比
    for i in range(0, len(lie)-1):
        # 当前元素与下一个相比, 如果相同则合并
        if lie[i] == lie[i+1]:
            lie[i] += lie[i + 1] # 相同则相加
            lie.pop(i + 1) # 删除相同的元素
            lie.append(0) # 在末尾追加0
# 测试代码
# merge(lie)
# print(lie)


#%% 3. 地图向左右移动

def merge_left(lie):
    """左移，
    将二维列表遍历出来的一维列表进行0移至末尾,然后进行合并
    """
    for r in lie: # 遍历二维列表
        merge(r) # 左移合并

def merge_rigft(lie):
    """右移，
    将二维列表遍历出来的一维列表进行0移至第一个位置,然后进行合并
    """
    for r in lie: # 遍历二维列表
        list_merge = r[::-1]    # 从右向左取出数据 形成 新列表
        merge(list_merge) # 合并
        r[::-1] = list_merge # 从右向左接受合并后的数据，所以需要返回覆盖旧的列表  
# merge_rigft(map)
# print(map)


#%% 3. 地图向上下移动
def transposition(lie):
    """
    传入长宽相等的二维列表，
    无需返回，直接更改
    """
    for c in range(1, len(lie)): # 列
        for r in range(c, len(lie)): # 行
            lie[r][c-1], lie[c-1][r] = lie[c-1][r], lie[r][c-1] # 行列交换

def move_up(lie):
    """向上移动
    """
    # 先转置，行列交换
    transposition(lie)
    # 在处理左交换
    merge_left(lie)
    # 最后转置回去，变成源代码
    transposition(lie)
    
def move_low(lie):
    """向下移动
    """
    # 先转置，行列交换
    transposition(lie)
    # 在处理右交换
    merge_rigft(lie)
    # 最后转置回去，变成源代码
    transposition(lie)

move_low(map)
print(map)

